package com.linkoog.devtools.type.swagger;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.linkoog.devtools.utils.PsiElementUtil;

import java.util.List;

public class JavaSwaggerParser {

    private static final String ApiAnno = "io.swagger.annotations.Api";
    private static final String ApiOperationAnno = "io.swagger.annotations.ApiOperation";
    private static final String ApiImplicitParamsAnno = "io.swagger.annotations.ApiImplicitParams";
    private static final String ApiModelPropertyAnno = "io.swagger.annotations.ApiModelProperty";

    // swagger 3.0
    private static final String TagAnno = "io.swagger.v3.oas.annotations.tags.Tag";
    private static final String OperationAnno = "io.swagger.v3.oas.annotations.Operation";
    private static final String SchemaAnno = "io.swagger.v3.oas.annotations.media.Schema";


    public static String parseClass(PsiClass psiClass){
        if (psiClass == null){
            return null;
        }

        PsiAnnotation annotation = ApplicationManager.getApplication().runReadAction((Computable<PsiAnnotation>) () -> psiClass.getAnnotation(ApiAnno));
        if (annotation != null){
            List<String> classRemarks = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "tags");
            if (classRemarks != null && !classRemarks.isEmpty()){
                return classRemarks.get(0);
            }
        }

        // swagger 3.0
        annotation = ApplicationManager.getApplication().runReadAction((Computable<PsiAnnotation>) () -> psiClass.getAnnotation(TagAnno));
        if (annotation != null){
            List<String> classRemarks = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "name");
            if (classRemarks != null && !classRemarks.isEmpty()){
                return classRemarks.get(0);
            }
        }

        return null;
    }

    public static String parseMethod(PsiMethod psiMethod){
        if (psiMethod == null){
            return null;
        }

        PsiAnnotation annotation = psiMethod.getAnnotation(ApiOperationAnno);
        if (annotation != null){
            List<String> classRemarks = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "value");
            if (classRemarks != null && !classRemarks.isEmpty()){
                return classRemarks.get(0);
            }
        }

        // swagger 3.0
        annotation = psiMethod.getAnnotation(OperationAnno);
        if (annotation != null){
            List<String> classRemarks = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "summary");
            if (classRemarks != null && !classRemarks.isEmpty()){
                return classRemarks.get(0);
            }
        }

        return "";
    }

    public static String parseMethodParam(PsiMethod psiMethod){
        if (psiMethod == null){
            return null;
        }

        PsiAnnotation annotation = psiMethod.getAnnotation(ApiImplicitParamsAnno);
        if (annotation == null){
            return null;
        }

        List<String> classRemarks = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "value");
        if (classRemarks != null && !classRemarks.isEmpty()){
            return classRemarks.get(0);
        }

        return "";
    }



    public static SwaggerFieldDoc parseField(PsiField psiField){
        if (psiField == null){
            return null;
        }

        PsiAnnotation annotation = psiField.getAnnotation(ApiModelPropertyAnno);
        if (annotation != null){
            SwaggerFieldDoc swagger = new SwaggerFieldDoc();
            List<String> classRemarks;

            classRemarks = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "required");
            if (classRemarks != null && !classRemarks.isEmpty()){
                final String required = classRemarks.get(0);
                swagger.setRequired("true".equals(required));
            }

            classRemarks = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "name");
            if (classRemarks != null && !classRemarks.isEmpty()){
                final String name = classRemarks.get(0);
                swagger.setName(name);
            }

            classRemarks = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "value");
            if (classRemarks != null && !classRemarks.isEmpty()){
                final String value = classRemarks.get(0);
                swagger.setValue(value);
            }

            classRemarks = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "example");
            if (classRemarks != null && !classRemarks.isEmpty()){
                final String example = classRemarks.get(0);
                swagger.setExample(example);
            }

            return swagger;
        }

        // swagger 3.0
        annotation = psiField.getAnnotation(SchemaAnno);
        if (annotation != null){
            SwaggerFieldDoc swagger = new SwaggerFieldDoc();
            List<String> temps;

            temps = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "required");
            if (temps != null && !temps.isEmpty()){
                final String required = temps.get(0);
                swagger.setRequired("true".equals(required));
            }

            temps = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "name");
            if (temps != null && !temps.isEmpty()){
                final String name = temps.get(0);
                swagger.setName(name);
            }

            temps = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "description");
            if (temps != null && !temps.isEmpty()){
                final String value = temps.get(0);
                swagger.setValue(value);
            }

            temps = PsiElementUtil.parsePsiAnnotationAttributeValue(annotation, "example");
            if (temps != null && !temps.isEmpty()){
                final String example = temps.get(0);
                swagger.setExample(example);
            }

            return swagger;
        }

        return null;
    }


}
